package com.ruoyi.web.controller.common;

import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.aliyun.oss.ClientException;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.ruoyi.common.exception.file.FileUploadException;
import com.ruoyi.common.scoket.PutObjectProgressListener;
import com.ruoyi.common.scoket.UploadProgressHandler;
import com.ruoyi.common.utils.OssUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import org.springframework.web.socket.WebSocketSession;

/**
 * 通用请求处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/common")
public class CommonController
{
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private ServerConfig serverConfig;

    private static final String FILE_DELIMETER = ",";

    @Autowired
    private UploadProgressHandler uploadProgressHandler;

    private static String accessKeyId = "LTAI5tQxBbtZ3yxC2FYSjTbA";
    private static String accessKeySecret = "md2YXFHvOT26NoByeInQN9mZGdLkBS";
    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete 是否删除
     */
    @GetMapping("/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
    {
        try
        {
            if (!FileUtils.checkAllowDownload(fileName))
            {
                throw new Exception(StringUtils.format("文件名称({})非法，不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = RuoYiConfig.getDownloadPath() + fileName;

            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete)
            {
                FileUtils.deleteFile(filePath);
            }
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }


    @GetMapping("/downloadOss")
    public void downloadOss(String url, HttpServletResponse response)
    {
        try
        {
            OssUtil.fileDownload(url,response);
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 通用上传请求（单个）
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception
    {
        try
        {
            // 上传文件路径
//            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
//            String fileName = FileUploadUtils.upload(filePath, file);
            String fileName = OssUtil.uploadMultipartFile(file);
//            String url = serverConfig.getUrl() + fileName;
            String url = fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 通用上传请求（多个）
     */
    @PostMapping("/uploads")
    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
    {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files)
            {
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = serverConfig.getUrl() + fileName;
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(FileUtils.getName(fileName));
                originalFilenames.add(file.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法，不允许下载。 ", resource));
            }
            // 本地资源路径
            String localPath = RuoYiConfig.getProfile();
            // 数据库资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }


    /**
     * 通用上传请求（单个）
     */
    @PostMapping("/uploadBigFile")
    public AjaxResult uploadBigFile(@RequestParam("file")MultipartFile file, @RequestParam("requestId")String requestId) throws Exception
    {
        //获取处理器监听到的WebSocketSession集合
        Map<String, WebSocketSession> sessionMap = UploadProgressHandler.getSessionMap();
        Collection<WebSocketSession> sessions = sessionMap.values();
        List<WebSocketSession> values = new ArrayList<>(sessions);
        int size = values.size();
        if (size<1){
            throw new FileUploadException("Websocket服务未连接！");
        }
//        // 关闭除最后一个之外的其他WebSocketSession
//        for (int i = 0; i < size - 1; i++) {
//            WebSocketSession session = values.get(i);
//            session.close();
//            sessionMap.remove(session.getId());
//        }
//        WebSocketSession webSocketSession = values.get(size-1);
        WebSocketSession webSocketSession = sessionMap.get(requestId);
        System.out.println(webSocketSession.getId());
        System.out.println(file.getSize());
        //添加websocket服务监听文件上传进程
        PutObjectProgressListener progressListener = new PutObjectProgressListener(webSocketSession, file.getSize());
        uploadProgressHandler.addProgressListener(requestId, progressListener);
        // 将 WebSocketSession 传递给 OSSUtil.uploadFile方法
        String fileName = OssUtil.uploadFile(file, requestId, webSocketSession);
        //上传完成，移除websocket服务监听
        uploadProgressHandler.removeProgressListener(requestId);

//        Map<String, String> resultMap = new HashMap<>();
//        resultMap.put("requestId", requestId);

        String url = fileName;
        AjaxResult ajax = AjaxResult.success();
        ajax.put("url", url);
        ajax.put("fileName", fileName);
        ajax.put("newFileName", FileUtils.getName(fileName));
        ajax.put("originalFilename", file.getOriginalFilename());

        return ajax;
    }



    /**
     * 获取阿里云的临时访问凭证
     */
    @GetMapping("/sts")
    public AjaxResult getSts(){
        AssumeRoleResponse.Credentials credentials = null;
        // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
        String endpoint = "sts.cn-beijing.aliyuncs.com";  //华北2(北京)

        // 新建的sts的accessKeyId   accessKeySecret
//        String accessKeyId = accessKeyId;
//        String accessKeySecret = accessKeyId;
        //    需要授权的角色名称
        String roleArn = "acs:ram::1363560832098431:role/ramosstest";
        String roleSessionName = "alice";
//    修改 Resource  abc 为自己的桶的名字
        String policy = "{\n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Action\": [\n" +
                "                \"oss:GetObject\",\n" +
                "                \"oss:PutObject\",\n" +
                "                \"oss:DeleteObject\",\n" +
                "                \"oss:ListParts\",\n" +
                "                \"oss:AbortMultipartUpload\",\n" +
                "                \"oss:ListObjects\"\n" +
                "            ],\n" +
                "            \"Effect\": \"Allow\",\n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:bridgebj/*\",\n" +
                "                \"acs:oss:*:*:bridgebj\"\n" +
                "            ]\n" +
                "        }\n" +
                "    ],\n" +
                "    \"Version\": \"1\"\n" +
                "}";
        try {
            // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
            DefaultProfile.addEndpoint("", "", "Sts", endpoint);
            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy); // Optional
            request.setProtocol(ProtocolType.HTTPS); // 必须使用HTTPS协议访问STS服务);
            final AssumeRoleResponse response = client.getAcsResponse(request);
            credentials = response.getCredentials();
        } catch (ClientException e) {
        } catch (ServerException e) {
            throw new RuntimeException(e);
        } catch (com.aliyuncs.exceptions.ClientException e) {
            throw new RuntimeException(e);
        }
        return AjaxResult.success(credentials);
    }


    /**
     * 删除oss文件（单个）
     */
    @GetMapping("/deleteOssFile")
    public AjaxResult deleteOssFile(@RequestParam("fileName") String fileName) throws Exception
    {
     OssUtil.deleteOssFile(fileName);

        return AjaxResult.success("删除成功");
    }


}
